"""
MinIO 对象存储服务
"""
from minio import Minio
from minio.error import S3Error
from app.core.config import settings
from loguru import logger
from typing import Optional, BinaryIO
from datetime import timedelta
import os
import uuid


class MinIOService:
    """MinIO 对象存储服务"""
    
    def __init__(self):
        """初始化 MinIO 客户端"""
        try:
            self.client = Minio(
                endpoint=settings.MINIO_ENDPOINT,
                access_key=settings.MINIO_ACCESS_KEY,
                secret_key=settings.MINIO_SECRET_KEY,
                secure=settings.MINIO_SECURE
            )
            self.bucket_name = settings.MINIO_BUCKET
            self.public_url = settings.MINIO_PUBLIC_URL
            
            # 确保 bucket 存在
            self._ensure_bucket_exists()
            
            logger.success(f"✅ MinIO 服务初始化成功: {settings.MINIO_ENDPOINT}/{self.bucket_name}")
        except Exception as e:
            logger.error(f"❌ MinIO 服务初始化失败: {e}")
            raise
    
    def _ensure_bucket_exists(self):
        """确保 bucket 存在"""
        try:
            # 检查bucket是否存在
            bucket_exists = self.client.bucket_exists(self.bucket_name)
            logger.info(f"🔍 检查 bucket: {self.bucket_name} - {'存在' if bucket_exists else '不存在'}")
            
            if not bucket_exists:
                # 创建bucket
                logger.info(f"📦 正在创建 bucket: {self.bucket_name}")
                self.client.make_bucket(self.bucket_name)
                logger.success(f"✅ Bucket 创建成功: {self.bucket_name}")
                
                # 设置 bucket 为公开访问
                import json
                policy = {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {"AWS": ["*"]},
                            "Action": ["s3:GetObject"],
                            "Resource": [f"arn:aws:s3:::{self.bucket_name}/*"]
                        }
                    ]
                }
                logger.info(f"🔓 正在设置 bucket 公开访问策略...")
                self.client.set_bucket_policy(self.bucket_name, json.dumps(policy))
                logger.success(f"✅ Bucket 公开访问策略设置成功")
            else:
                logger.info(f"✅ Bucket 已存在: {self.bucket_name}")
        except S3Error as e:
            logger.error(f"❌ 检查/创建 bucket 失败: {e}")
            logger.error(f"   错误详情: code={e.code}, message={e.message}")
            raise
        except Exception as e:
            logger.error(f"❌ Bucket 初始化异常: {e}")
            raise
    
    def upload_file(
        self,
        file_obj: BinaryIO,
        file_name: str,
        content_type: str = "application/octet-stream",
        folder: str = "uploads"
    ) -> str:
        """
        上传文件到 MinIO
        
        Args:
            file_obj: 文件对象
            file_name: 文件名
            content_type: 文件类型
            folder: 存储文件夹
        
        Returns:
            文件的公开访问 URL
        """
        try:
            # 生成唯一文件名
            file_ext = os.path.splitext(file_name)[1]
            unique_name = f"{uuid.uuid4().hex}{file_ext}"
            object_name = f"{folder}/{unique_name}"
            
            # 获取文件大小
            file_obj.seek(0, os.SEEK_END)
            file_size = file_obj.tell()
            file_obj.seek(0)
            
            logger.info(f"📤 上传文件: {object_name} ({file_size} bytes)")
            
            # 上传文件
            self.client.put_object(
                bucket_name=self.bucket_name,
                object_name=object_name,
                data=file_obj,
                length=file_size,
                content_type=content_type
            )
            
            # 返回公开访问 URL
            file_url = f"{self.public_url}/{self.bucket_name}/{object_name}"
            logger.success(f"✅ 文件上传成功: {file_url}")
            
            return file_url
        except S3Error as e:
            logger.error(f"❌ 文件上传失败: {e}")
            raise
    
    def upload_file_from_path(
        self,
        file_path: str,
        content_type: Optional[str] = None,
        folder: str = "uploads"
    ) -> str:
        """
        从本地路径上传文件
        
        Args:
            file_path: 本地文件路径
            content_type: 文件类型（自动检测）
            folder: 存储文件夹
        
        Returns:
            文件的公开访问 URL
        """
        try:
            file_name = os.path.basename(file_path)
            
            # 自动检测 content_type
            if content_type is None:
                ext = os.path.splitext(file_name)[1].lower()
                content_type_map = {
                    '.jpg': 'image/jpeg',
                    '.jpeg': 'image/jpeg',
                    '.png': 'image/png',
                    '.gif': 'image/gif',
                    '.pdf': 'application/pdf',
                    '.mp4': 'video/mp4',
                    '.mp3': 'audio/mpeg'
                }
                content_type = content_type_map.get(ext, 'application/octet-stream')
            
            with open(file_path, 'rb') as file_obj:
                return self.upload_file(file_obj, file_name, content_type, folder)
        except Exception as e:
            logger.error(f"❌ 从路径上传文件失败: {e}")
            raise
    
    def delete_file(self, file_url: str) -> bool:
        """
        删除文件
        
        Args:
            file_url: 文件的公开访问 URL
        
        Returns:
            是否删除成功
        """
        try:
            # 从 URL 提取 object_name
            # 例如: http://localhost:9000/football/uploads/xxx.jpg -> uploads/xxx.jpg
            object_name = file_url.split(f"/{self.bucket_name}/")[-1]
            
            logger.info(f"🗑️  删除文件: {object_name}")
            
            self.client.remove_object(
                bucket_name=self.bucket_name,
                object_name=object_name
            )
            
            logger.success(f"✅ 文件删除成功: {object_name}")
            return True
        except S3Error as e:
            logger.error(f"❌ 文件删除失败: {e}")
            return False
    
    def get_presigned_url(
        self,
        object_name: str,
        expires: timedelta = timedelta(hours=1)
    ) -> str:
        """
        获取文件的预签名 URL（临时访问链接）
        
        Args:
            object_name: 对象名称
            expires: 过期时间
        
        Returns:
            预签名 URL
        """
        try:
            url = self.client.presigned_get_object(
                bucket_name=self.bucket_name,
                object_name=object_name,
                expires=expires
            )
            return url
        except S3Error as e:
            logger.error(f"❌ 获取预签名 URL 失败: {e}")
            raise


# 创建全局 MinIO 服务实例
try:
    minio_service = MinIOService()
except Exception as e:
    logger.warning(f"⚠️  MinIO 服务不可用: {e}")
    minio_service = None

